﻿using Fluid;
using KWT.DRG_DIP.API.Infrastructure;
using KWT.DRG_DIP.DB;
using KWT.DRG_DIP.DTO.Basic.Menu;
using KWT.DRG_DIP.PO;
using KWT.DRG_DIP.PO.Basic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Parlot.Fluent;

namespace KWT.DRG_DIP.API.Controllers.Basic
{
    /// <summary>
    /// 菜单
    /// </summary>
    [ApiExplorerSettings(GroupName = "basic")]
    public class MenuController : BasicControllerBase
    {
        public EFContext ef { get; set; }
        public FluidParser fluid { get; set; }
        /// <summary>
        /// 根据模块ID得到左侧树形菜单
        /// </summary>
        /// <param name="moduleID">模块ID</param>
        /// <returns></returns>
        [HttpGet]
        public OutputResult GetTreeListByModuleID(string moduleID)
        {
            var all = ef.Set<Sys_Menu>().Where(x => x.ModuleID == moduleID).ToList();
            var context = new TemplateContext(new { UsePolicy = CurrentUser.UsePolicy });
            all.ForEach(x =>
            {
                if (fluid.TryParse(x.Title, out var template, out var error))
                {
                    x.Title = template.Render(context);
                }
            });
            
            var dic = new Dictionary<string, OutTree>(all.Count);

            foreach (var trade in all)
            {
                var tree = new OutTree()
                {
                    title = trade.Title,
                    value = trade.MenuID,
                    pid = trade.PID,
                    id = trade.MenuID,
                    icon = trade.Icon,
                    moduleID = trade.ModuleID
                    //disabled = trade.ParentID == ""
                };
                dic.Add(trade.MenuID, tree);
            }

            //通过一次遍历集合，转换成具有层次结构的类型
            foreach (var menu in dic.Values)
            {
                if (dic.ContainsKey(menu.pid))
                {
                    if (dic[menu.pid].children == null)
                        dic[menu.pid].children = new List<OutTree>() { };

                    dic[menu.pid].children.Add(menu);
                }
            }

            //仅仅选择最顶层节点返回
            var list = dic.Values.Where(t => t.pid == "").ToList();
            return Output(true, "", "", list);
        }

        /// <summary>
        /// 树形菜单
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public OutputResult TreeList()
        {
            var all = ef.Set<Sys_Menu>().ToList();
            var context = new TemplateContext(new { UsePolicy = CurrentUser.UsePolicy });
            all.ForEach(x =>
            {
                if (fluid.TryParse(x.Title, out var template, out var error))
                {
                    x.Title = template.Render(context);
                }
            });
            var dic = new Dictionary<string, OutTree>(all.Count);

            foreach (var trade in all)
            {
                var tree = new OutTree()
                {
                    title = trade.Title,
                    value = trade.MenuID,
                    pid = trade.PID,
                    id = trade.MenuID,
                    icon = trade.Icon
                    //disabled = trade.ParentID == ""
                };
                dic.Add(trade.MenuID, tree);
            }

            //通过一次遍历集合，转换成具有层次结构的类型
            foreach (var menu in dic.Values)
            {
                if (dic.ContainsKey(menu.pid))
                {
                    if (dic[menu.pid].children == null)
                        dic[menu.pid].children = new List<OutTree>() { };

                    dic[menu.pid].children.Add(menu);
                }
            }

            //仅仅选择最顶层节点返回
            var list = dic.Values.Where(t => t.pid == "").ToList();
            return Output(true, "", "", list);
        }

        /// <summary>
        /// 树形菜单(角色)
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public OutputResult Role()
        {
            var q1 = ef.Set<Sys_Menu>().AsQueryable();
            var q2 = ef.Set<Role_Menu>().AsQueryable();
            var roleIDs = CurrentUser.RoleIDs;
            var list = (from x in q1
                        join y in q2
                        on x.MenuID equals y.MenuID
                        where roleIDs.Contains(y.RoleID)
                        orderby x.Sort
                        select x).ToList();
            var context = new TemplateContext(new { UsePolicy = CurrentUser.UsePolicy });
            list.ForEach(x =>
            {
                if (fluid.TryParse(x.Title, out var template, out var error))
                {
                    x.Title = template.Render(context);
                }
            });

            return Output(true, "", "", list);
        }

        /// <summary>
        /// 路由表
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public OutputResult RouteList()
        {
            var q1 = ef.Set<Sys_Menu>().AsQueryable();
            var q2 = ef.Set<Role_Menu>().AsQueryable();
            var q3 = ef.Set<User_AreaRoleDeptCategory>().AsQueryable();

            var roleIDs = q3.Where(x => x.UserID == CurrentUser.UserID).Select(x => x.RoleID).ToList();

            var list = (from x in q1
                        join y in q2 on x.MenuID equals y.MenuID
                        join z in q3 on y.RoleID equals z.RoleID

                        where roleIDs.Contains(y.RoleID) && x.PID != ""
                        orderby x.Sort
                        select x).ToList();
            return Output(true, "", "", list);
        }

        /// <summary>
        /// 添加角色
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddRole(InAddRole dto)
        {
            var list = new List<Role_Menu>();
            foreach (var item in dto.MenuID)
            {
                foreach (var item2 in dto.RoleID)
                {
                    var rm = new Role_Menu()
                    {
                        RMID = "RM" + snow_id.CreateId().ToString(),
                        MenuID = item,
                        RoleID = item2
                    };
                    if (!ef.Set<Role_Menu>().Any(x => x.MenuID == item && x.RoleID == item2))
                    {
                        list.Add(rm);
                    }
                }
            }
            ef.AddRange(list);
            var flag = ef.SaveChanges() > 0;
            return Output(flag, "添加成功！", "添加失败！指定菜单已经获得该权限。");
        }

        /// <summary>
        /// 添加功能
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddFunc(InAddFunc dto)
        {
            var list = new List<Menu_Func>();
            foreach (var item in dto.MenuID)
            {
                foreach (var item2 in dto.FuncID)
                {
                    var mf = new Menu_Func()
                    {
                        MFID = "MF" + snow_id.CreateId().ToString(),
                        MenuID = item,
                        FuncID = item2
                    };
                    if (!ef.Set<Menu_Func>().Any(x => x.MenuID == item && x.FuncID == item2))
                    {
                        list.Add(mf);
                    }
                }
            }
            ef.AddRange(list);
            var flag = ef.SaveChanges() > 0;
            return Output(flag, "添加成功！", "添加失败！指定菜单已经获得该功能。");
        }

        /// <summary>
        /// 移除角色
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult RemoveRole(InRemoveRole dto)
        {
            var flag = ef.Set<Role_Menu>().Where(x => dto.RoleID.Contains(x.RoleID) && dto.MenuID.Contains(x.MenuID)).ExecuteDelete() > 0;
            return Output(flag, "移除成功！", "移除失败！");
        }

        /// <summary>
        /// 移除功能
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult RemoveFunc(InAddFunc dto)
        {
            var flag = ef.Set<Menu_Func>().Where(x => dto.MenuID.Contains(x.MenuID) && dto.FuncID.Contains(x.FuncID)).ExecuteDelete() > 0;
            return Output(flag, "移除成功！", "移除失败！");
        }

        /// <summary>
        /// 根据菜单得到角色
        /// </summary>
        /// <param name="menuID"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetRoleByMenuID(string menuID)
        {
            var list = ef.Set<Role_Menu>().Where(x => x.MenuID == menuID).Select(x => x.RoleID).ToList();
            return Output(list != null, "", "", list);
        }

        /// <summary>
        /// 根据菜单得到功能
        /// </summary>
        /// <param name="menuID"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult GetFuncByMenuID(string menuID)
        {
            var list = ef.Set<Menu_Func>().Where(x => x.MenuID == menuID).Select(x => x.FuncID).ToList();
            return Output(list != null, "", "", list);
        }

        /// <summary>
        /// 添加菜单
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult AddOrUpdate(InAddOrUpdate dto)
        {
            bool flag = false;
            int max = 0;

            if (dto.type != -2)
            {
                if (!string.IsNullOrWhiteSpace(dto.name))
                {
                    if (ef.Set<Sys_Menu>().Any(x => x.Name == dto.name))
                    {
                        return Fail("路由名称已存在！");
                    }
                }

                if (dto.type == 1)//添加上级
                {
                    if (ef.Set<Sys_Menu>().Any(x => x.PID == dto.id))
                    {
                        max = ef.Set<Sys_Menu>().Where(x => x.PID == dto.id).Max(x => x.Sort);
                    }
                    var menu = _mapper.Map<Sys_Menu>(dto);
                    menu.MenuID = "MN" + snow_id.CreateId().ToString();
                    menu.Sort = max + 1;
                    ef.Add(menu);
                    var menus = ef.Set<Sys_Menu>().Where(x => x.PID == dto.pid).ToList();
                    menus.ForEach(x => x.PID = menu.MenuID);
                    ef.AttachRange(menus);
                    flag = ef.SaveChanges() > 0;
                }
                if (dto.type == 0)//添加同级
                {
                    if (ef.Set<Sys_Menu>().Any(x => x.PID == dto.pid && x.Title == dto.title))
                    {
                        return Fail("您输入的菜单名称已存在于同级菜单下！");
                    }
                    if (ef.Set<Sys_Menu>().Any(x => x.PID == dto.id))
                    {
                        max = ef.Set<Sys_Menu>().Where(x => x.PID == dto.pid).Max(x => x.Sort);
                    }
                    var menu = _mapper.Map<Sys_Menu>(dto);
                    menu.MenuID = "MN" + snow_id.CreateId().ToString();
                    menu.Sort = max + 1;
                    ef.Add(menu);
                    flag = ef.SaveChanges() > 0;
                }
                if (dto.type == -1)//添加下级
                {
                    if (ef.Set<Sys_Menu>().Any(x => x.PID == dto.id))
                    {
                        max = ef.Set<Sys_Menu>().Where(x => x.PID == dto.id).Max(x => x.Sort);
                    }
                    var menu = _mapper.Map<Sys_Menu>(dto);
                    menu.MenuID = "MN" + snow_id.CreateId().ToString();
                    menu.PID = dto.id;
                    menu.Sort = max + 1;
                    ef.Add(menu);
                    flag = ef.SaveChanges() > 0;
                }
            }
            else
            {
                var menu = ef.Find<Sys_Menu>(dto.id);
                menu.Title = dto.title;
                menu.Icon = dto.icon;
                menu.Path = dto.path;
                menu.Name = dto.name;
                menu.Component = dto.component;
                ef.Attach(menu);
                flag = ef.SaveChanges() > 0;
            }
            return Output(flag, "操作成功！", "操作失败！");
        }

        /// <summary>
        /// 详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Detail(string id)
        {
            var menu = ef.Find<Sys_Menu>(id);
            return Output(menu != null, "", "", menu);
        }

        /// <summary>
        /// 移动
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public OutputResult Move(InMove dto)
        {
            var from = ef.Find<Sys_Menu>(dto.MenuID);
            var list = ef.Set<Sys_Menu>().Where(x => x.PID == from.PID).OrderBy(x => x.Sort).ToList();
            int index = list.IndexOf(from);
            if (dto.Type == 1)
            {
                if (index == 0)
                {
                    return Fail("抱歉！已经是该级的第一个菜单，不允许跨级移动！");
                }
                var to = list.ElementAt(index - 1);

                if (to.Sort == from.Sort)
                {
                    from.Sort -= 1;
                }
                else
                {
                    int to_sort = to.Sort;
                    to.Sort = from.Sort;
                    from.Sort = to_sort;
                }

                ef.Update(from);
                ef.Update(to);
            }
            else
            {
                if (index == list.Count - 1)
                {
                    return Fail("抱歉！已经是该级的最后一个菜单，不允许跨级移动！");
                }
                var to = list.ElementAt(index + 1);

                if (to.Sort == from.Sort)
                {
                    from.Sort -= 1;
                }
                else
                {
                    int to_sort = to.Sort;
                    to.Sort = from.Sort;
                    from.Sort = to_sort;
                }

                ef.Update(from);
                ef.Update(to);
            }


            var result = ef.SaveChanges() > 0;
            return Output(result, "操作成功！", "操作失败！");
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        [HttpPost]
        public OutputResult Del(InDel dto)
        {
            var flag = ef.Set<Sys_Menu>().Where(x => dto.MenuIDs.Contains(x.MenuID)).ExecuteDelete() > 0;
            return Output(flag, "删除成功！", "删除失败！");
        }
    }
}
